﻿using System;
using System.Collections.ObjectModel;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
using System.Windows.Threading;
using System.Diagnostics;

namespace YouTube
{
	/// <summary>Interaction logic for YouTubeWindow.xaml</summary>
	public partial class YouTubeWindow : Window
	{
		private ObservableCollection<YouTubeVideo> videos = new ObservableCollection<YouTubeVideo>();
		public ObservableCollection<YouTubeVideo> Videos { get { return videos; } }

		DispatcherTimer seekTimer;

		public YouTubeWindow()
		{
			InitializeComponent();

			CommandBindings.Add(new CommandBinding(ApplicationCommands.Open, searchCommand_Executed));

			seekTimer = new DispatcherTimer(DispatcherPriority.Background, Dispatcher);
			seekTimer.IsEnabled = false;
			seekTimer.Interval = TimeSpan.FromMilliseconds(500);
			seekTimer.Tick += seekTimer_Tick;
		}

		private void seekTimer_Tick(object sender, EventArgs e)
		{
			if(mediaElement != null)
			{
				TimeSpan t = mediaElement.Position;
				TimeSpan d = TimeSpan.Zero;
				if(mediaElement.NaturalDuration.HasTimeSpan)
					d = mediaElement.NaturalDuration.TimeSpan;
				mediaElementSlider.Value = t.TotalMilliseconds;
				mediaElementTextBlock.Text = string.Format("{0:D2}:{1:D2}:{2:D2} / {3:D2}:{4:D2}:{5:D2}", t.Hours, t.Minutes, t.Seconds, d.Hours, d.Minutes, d.Seconds);
			}
		}

		private void stopAndCloseVideo()
		{
			mediaElement.Close();
			mediaElement.Source = null;
			mediaPlayer.Visibility = Visibility.Collapsed;
		}

		private void searchCommand_Executed(object sender, ExecutedRoutedEventArgs e)
		{
			string query = e.Parameter.ToString();
			videos.Clear();

			YouTubeProvider.SearchAsync(query,
				(result, ex) =>
				{
					if(ex != null)
					{
						MessageBox.Show(this, ex.Message, "Search error", MessageBoxButton.OK, MessageBoxImage.Error);
					}
					else
					{
						foreach(var video in result)
							videos.Add(video);

						// HACK: Keep scrolling from last search otherwise
						if(videos.Count > 0)
							videosListBox.ScrollIntoView(videos[0]);
					}
				});
		}

		private void mediaElement_MediaOpened(object sender, RoutedEventArgs e)
		{
			mediaElementStatus.Text = "MediaOpened";
			mediaElement.Width = mediaElement.NaturalVideoWidth;
			mediaElement.Height = mediaElement.NaturalVideoHeight;
			CommandManager.InvalidateRequerySuggested();

			mediaElementSlider.Maximum = mediaElement.NaturalDuration.TimeSpan.TotalMilliseconds;
			seekTimer.IsEnabled = true;
		}

		private void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
		{
			mediaElementStatus.Text = "MediaEnded";
			CommandManager.InvalidateRequerySuggested();

			seekTimer.IsEnabled = false;
		}

		private void mediaElement_MediaFailed(object sender, ExceptionRoutedEventArgs e)
		{
			mediaElementStatus.Text = "MediaFailed: " + e.ErrorException.Message;
			CommandManager.InvalidateRequerySuggested();
		}

		private void mediaElement_BufferingStarted(object sender, RoutedEventArgs e)
		{
			mediaElementStatus.Text = "BufferingStarted";
			CommandManager.InvalidateRequerySuggested();
		}

		private void mediaElement_BufferingEnded(object sender, RoutedEventArgs e)
		{
			mediaElementStatus.Text = "BufferingEnded";
			CommandManager.InvalidateRequerySuggested();
		}

		private void VideoItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
		{
			YouTubeVideo video = (YouTubeVideo)((VideoItem)sender).DataContext;
			if(video.FileUri != null)
			{
				mediaElement.Source = video.FileUri;
				mediaElement.Play();
				mediaPlayer.Visibility = Visibility.Visible;
				CommandManager.InvalidateRequerySuggested();
			}
		}

		private void mediaPlayer_MouseDoubleClick(object sender, MouseButtonEventArgs e)
		{
			stopAndCloseVideo();
		}

		private void TogglePlayPauseCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = mediaElement != null && mediaElement.Source != null;
		}

		private void TogglePlayPauseCommand_Executed(object sender, ExecutedRoutedEventArgs e)
		{
			if(seekTimer.IsEnabled)
			{
				mediaElement.Pause();
				seekTimer.IsEnabled = false;
			}
			else
			{
				mediaElement.Play();
				seekTimer.IsEnabled = true;
			}
		}

		private void PlayCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = mediaElement != null && mediaElement.Source != null;
		}

		private void PlayCommand_Executed(object sender, ExecutedRoutedEventArgs e)
		{
			mediaElement.Play();
			seekTimer.IsEnabled = true;
		}

		private void PauseCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = mediaElement != null && mediaElement.CanPause;
		}

		private void PauseCommand_Executed(object sender, ExecutedRoutedEventArgs e)
		{
			mediaElement.Pause();
			seekTimer.IsEnabled = false;
		}

		private void StopCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = mediaElement != null && mediaElement.Source != null;
		}

		private void StopCommand_Executed(object sender, ExecutedRoutedEventArgs e)
		{
			mediaElement.Position = TimeSpan.Zero;
			mediaElement.Stop();
			seekTimer.IsEnabled = false;
		}

		private void playInMpc_Click(object sender, RoutedEventArgs e)
		{
			string mpcPath = @"C:\Program Files (x86)\MPC-HC\mpc-hc.exe";
			string args = string.Format("\"{0}\" /play /fullscreen", mediaElement.Source);

			ProcessStartInfo psi = new ProcessStartInfo(mpcPath, args);
			Process process = Process.Start(psi);

			stopAndCloseVideo();
		}
	}
}
